#pragma once

#include <iostream>
#include <unordered_map>
#include <memory>
#include "Connection.hpp"
#include "Epoller.hpp"

using connection_t = std::shared_ptr<Connection>;

// 事件派发器
class Reactor
{
    const static int event_num = 64;
    
    bool IsConnectionExists(int sockfd)
    {
        return _connections.find(sockfd) != _connections.end();
    }
public:
    Reactor()
    :_epoller(std::make_unique<Epoller>())
    ,_isrunning(false)
    {
        _epoller->Init();
    }

    void InsertConnection(connection_t conn)
    {
        auto iter = _connections.find(conn->GetSockfd());
        if (iter == _connections.end())
        {
            // 1.插入连接,放到unordered_map统一管理
            _connections.insert(std::make_pair(conn->GetSockfd(), conn));
            // 2.添加到epoll模型中,默认以ET方式开启读事件的关心
            _epoller->Add(conn->GetSockfd(), conn->GetEvents());
            // 3.设置回指指针
            conn->SetOwner(this);
            LOG(LogLevel::INFO) << "add connection success, sockfd: " << conn->GetSockfd();
        }
    }

    void EnableReadWrite(int sockfd, bool read, bool write)
    {
        if (IsConnectionExists(sockfd))
        {
            uint32_t events = (read ? EPOLLIN : 0) | (write ? EPOLLOUT : 0) | EPOLLET;
            _connections[sockfd]->SetEvents(events);    // 记得修改连接关心的事件
            _epoller->Update(sockfd, events);
        }
    }

    void DeleteConnection(int sockfd)
    {
        if (IsConnectionExists(sockfd))
        {
            // 1.删除epoll模型中对该fd的关心
            _epoller->Delete(sockfd);
            // 2.关闭文件
            _connections[sockfd]->Close();
            // 3.移除unordered_map中的连接
            _connections.erase(sockfd);
        }
    }

    void Dispatcher(int rnum)
    {
        // 如果返回0/-1不会进入循环
        for (int i = 0; i < rnum; i++)
        {
            int fd = _revs[i].data.fd;
            uint32_t revents = _revs[i].events;
            // epoll出错或对方把连接关了，直接转换成读写错误进行处理
            if ((revents & EPOLLERR) || (revents & EPOLLHUP)) 
                revents = EPOLLIN | EPOLLOUT;
            if ((revents & EPOLLIN) && IsConnectionExists(fd))
                _connections[fd]->Recver();
            if ((revents & EPOLLOUT) && IsConnectionExists(fd))
                _connections[fd]->Sender();
        }
    }

    void LoopOnce(int timeout)
    {
        int n = _epoller->Wait(_revs, event_num, timeout);
        Dispatcher(n);
    }

    void Loop()
    {
        int timeout = -1;
        _isrunning = true;
        while (_isrunning)
        {
            LoopOnce(timeout);
            DebugPrint();
            // 超时管理——TODO
        }
        _isrunning = false;
    }

    void DebugPrint()
    {
        std::cout << "Epoller管理的fd: ";
        for (auto& iter : _connections)
        {
            std::cout << iter.first << " ";
        }
        std::cout << "\n";
    }

    ~Reactor()
    {}
private:
    std::unique_ptr<Epoller> _epoller;                  // epoll模型
    std::unordered_map<int, connection_t> _connections; // 管理所有连接
    bool _isrunning;                                    // 是否启动
    struct epoll_event _revs[event_num];                // 存储epoll_wait返回的信息
};